import base64
import datetime
import sys

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Hash import SHA256, SHA1
from Crypto.Signature import pss
import smtplib
from email.mime.text import MIMEText
from email.header import Header

import requests
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import pyqtSignal, QTimer, QDate, QDateTime, Qt
from PyQt5.QtWidgets import (QWidget, QApplication, QMessageBox, QTableWidgetItem)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
import json

import apiunit
from login_window import Ui_LoginWindow
from main_window import Ui_MainWindow

class LoginFrom(QtWidgets.QMainWindow, Ui_LoginWindow):

    sendToken = pyqtSignal(str)

    def __init__(self):
        super(LoginFrom, self).__init__()
        self.setupUi(self)
        self.login_btn.clicked.connect(self.login_click)
        self.close_btn.clicked.connect(self.login_close)

        self.setWindowTitle("中远抢拍助手v1.0")
        self.setFixedSize(self.width(), self.height())
        self.headers = {
            "Accept": "application/json, text/plain, */*",
            "Accept-Language": "zh-CN,zh-TW;q=0.9,zh;q=0.8,en-US;q=0.7,en;q=0.6",
            "Content-Type": "application/x-www-form-urlencoded",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36",
        }
        self.x_auth_token = ''
        self.initUI()

    def initUI(self):
        self.get_captcha_cookie()
        self.login_captcha = ''  # 登录认证
        self.x_auth_token = ''

        # 默认登录
        # self.username.setText('sunporty')
        # self.password.setText('cs@sp202021')
        self.login_url = 'https://synconhub.coscoshipping.com/api/admin/user/login'  # 登录
        self.graphics_captcha.mousePressEvent = self.update_captcha_img

    def get_captcha_cookie(self):
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        driver = webdriver.Chrome(executable_path='./tools/chromedriver', chrome_options=chrome_options)
        driver.get("https://synconhub.coscoshipping.com/")  #打开首页

        # cookie同意
        driver.find_element_by_xpath(
            '//*[@id="app"]/div/div[3]/div[2]/div/div/div[3]/div/div/div/div/div[2]/button[1]/span').click()
        time.sleep(0.5)

        cookie_list = driver.get_cookies()
        self.cookie_dict = {}
        for cookie in cookie_list:
            self.cookie_dict[cookie['name']] = cookie['value']
        self.update_captcha_img()

    #更新验证码
    def update_captcha_img(self, event = None):
        captcha_img_url = "https://synconhub.coscoshipping.com/api/common/captcha/image?d=%d" % (time.time())
        captcha_img = requests.get(captcha_img_url, cookies=self.cookie_dict)
        print("=======验证码状态=======")
        print(captcha_img)
        with open('captcha_img.png', 'wb') as f:
            f.write(captcha_img.content)
            f.close()
            print('下载验证码')

        self.login_captcha = self.cookie_dict['ECTIMGCAPTCHA']  # 获得登录验证串
        self.graphics_captcha.setStyleSheet("border-image: url(./captcha_img.png);")
        print("update captcha_img")

    #登录提交
    def login_click(self):
        self.uname_txt = self.username.currentText()
        self.pwd_txt = self.password.text()
        self.captcha_txt = self.captcha_code.text()
        login_headers_data = {"ECTIMGCAPTCHA" : self.login_captcha}
        body = {'username': self.uname_txt, 'password': apiunit.pwd_rsa_encrypt(self.pwd_txt), 'captcha': self.captcha_txt}
        headers = {**self.headers, **login_headers_data}
        print("=======正在登录=========")
        res = requests.post(url=self.login_url, headers=headers, data=body)
        print(res.status_code)
        if res.status_code != 200:
            json_obj = json.loads(res.json()['message'])
            QMessageBox.information(self, '提示', json_obj['message'], QMessageBox.Yes)
            return
        self.x_auth_token = res.headers['X-Auth-Token']  #获取登录token
        self.sendToken.emit(self.x_auth_token)
        mainw.show()
        self.close()

    def login_close(self):
        self.close()


#主窗口
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.setWindowTitle("中远抢拍助手v1.0")
        self.setFixedSize(self.width(), self.height())

        self.timer = QTimer()
        self.timer.timeout.connect(self.runTask)
        self.startBtn.clicked.connect(self.startBtnClick)
        self.stopBtn.clicked.connect(self.stopBtnClick)
        self.headers = {
            "Accept": "application/json, text/plain, */*",
            "Accept-Language": "zh-CN,zh-TW;q=0.9,zh;q=0.8,en-US;q=0.7,en;q=0.6",
            "Content-Type": "application/json;charset=UTF-8",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36",
        }
        self.tradeGroupcomBox.addItems(apiunit.airway_items)
        self.dateTimeEdit.setMinimumDate(QDate.currentDate().addDays(0))#设置最小日期
        now_time = time.strftime("%Y-%m-%d 23:50:00", time.localtime())
        end_date = (datetime.datetime.now() + datetime.timedelta(days=90)).strftime("%Y-%m-%d %H:%M:%S")
        #开航时间
        self.start_dateEdit.setDateTime(QDateTime.fromString(now_time, 'yyyy-MM-dd hh:mm:ss'))
        self.end_dateEdit.setDateTime(QDateTime.fromString(end_date, 'yyyy-MM-dd hh:mm:ss'))
        self.dateTimeEdit.setDateTime(QDateTime.fromString(now_time, 'yyyy-MM-dd hh:mm:ss'))
        self.bl_chombox.setCurrentIndex(1)
        self.twentyGP.setCurrentIndex(1)
        self.booking = 0  #下单状态
        self.paypass_edit.setMaxLength(6)

    def setWidgetDisabled(self, status = True):
        self.dateTimeEdit.setDisabled(status)
        self.tradeGroupcomBox.setDisabled(status)
        self.paypass_edit.setDisabled(status)
        self.tradeGroupcomBox.setDisabled(status)
        self.twentyGP.setDisabled(status)
        self.fortyHQ.setDisabled(status)
        self.fortyGP.setDisabled(status)
        self.twentyGP.setDisabled(status)
        self.bl_chombox.setDisabled(status)
        self.startBtn.setDisabled(status)
        self.start_dateEdit.setDisabled(status)
        self.end_dateEdit.setDisabled(status)

    def handleRunMsg(self, val):
        print("运行信息: " + val)
        self.textBrowser.append("运行信息: " + val)
        self.textBrowser.moveCursor(self.textBrowser.textCursor().atBlockEnd())

    def startBtnClick(self):
        start_datetime = self.dateTimeEdit.dateTime()
        if start_datetime < QDateTime.currentDateTime():
            print('抢仓时间不能小于当前时间')
            QMessageBox.information(self, '提示', "抢仓时间不能小于当前时间", QMessageBox.Yes)
            return

        if(len(self.paypass_edit.text()) != 6):
            QMessageBox.information(self, '提示', "请设置6位支付密码", QMessageBox.Yes)
            return

        self.twentygp_num = int(self.twentyGP.currentText())
        self.fortygp_num = int(self.fortyGP.currentText())
        self.fortyhq_num = int(self.fortyHQ.currentText())
        self.bl_num = int(self.bl_chombox.currentText())
        #
        if self.twentygp_num == 0 and self.fortygp_num == 0 and self.fortyhq_num == 0:
            QMessageBox.information(self, '提示', "至少选择一个箱型数量", QMessageBox.Yes)
            return
        if  self.bl_num== 0:
            QMessageBox.information(self, '提示', "保价服务至少选择一个", QMessageBox.Yes)
            return
        if(self.bl_num > (self.twentygp_num + self.fortygp_num + self.fortyhq_num)):
            QMessageBox.information(self, '提示', "保价数量不能大于下单箱数", QMessageBox.Yes)

        now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        msg = "下单参数: 20gp=%d 40gp=%d 40hq=%d 保价服务=%d" %(self.twentygp_num, self.fortygp_num, self.fortyhq_num, self.bl_num)
        self.textlog(msg)
        self.setWidgetDisabled(True)
        self.timer.start(500)

        self.textlog("定时任务已开始")

    def runTask(self):
        current_time = QDateTime.currentDateTime().toPyDateTime()
        start_time = self.dateTimeEdit.dateTime().toPyDateTime()
        diff_sec = abs((current_time - start_time).total_seconds())
        if current_time < start_time and int(diff_sec) <= 30 and int(diff_sec) != 0:
            self.textlog("%s秒后开始" % (diff_sec))
            return

        if ((current_time - start_time).total_seconds() > 3):
            self.textlog("抢仓结束")
            self.stopBtn.click()
            return

        print((current_time - start_time).total_seconds())
        if((current_time - start_time).total_seconds() <=  0):
            return
        try:
            self.textlog("正在请求库存")
            res = requests.post("https://synconhub.coscoshipping.com/api/product/client/sailing/product/list",
                                headers=self.headers,
                                data=json.dumps(
                                    apiunit.buildProduct(
                                        self.tradeGroupcomBox.currentIndex(),
                                        self.start_dateEdit.dateTime().toPyDateTime().strftime("%Y-%m-%d 00:00"),
                                        self.end_dateEdit.dateTime().toPyDateTime().strftime("%Y-%m-%d 00:00")
                                    )))
            print(res)
            if res.status_code != 200:
                self.textlog("服务器返回 %s", res.json())
                print(res.json())
                return

            if res.status_code == 200:
                content = res.json()['content']
                total_items = len(content)
                self.textlog("获取到 %d 条数据" % (total_items))
                self.tableWidget.setRowCount(total_items)
                for key, value in enumerate(content):
                    idItem = QTableWidgetItem(value['id'])
                    firstItem = QTableWidgetItem(value['firstPolPort']['portFullNameCn'])
                    fndItem = QTableWidgetItem(value['fndCity']['cityFullNameCn'])
                    daysItem = QTableWidgetItem(str(value['estimatedTransitTimeInDays']))
                    inventoryItem = QTableWidgetItem(str(value['inventory']))
                    self.tableWidget.setItem(key, 0, idItem)
                    self.tableWidget.setItem(key, 1, firstItem)
                    self.tableWidget.setItem(key, 2, fndItem)
                    self.tableWidget.setItem(key, 3, daysItem)
                    self.tableWidget.setItem(key, 4, inventoryItem)
                    if value['inventory'] > 0 and self.booking == 0:
                        self.textlog(msg = "获取到id=%s 剩余库存=%d" % (value['id'], int(value['inventory'])))
                        self.textlog("正在下单")
                        self.booking = 1
                        #获取下单参数
                        order_payload = apiunit.api_searchfee(
                            self.auth_token,
                            value['id'],
                            bl_quantity=int(self.bl_chombox.currentText()),
                            twenty_gp_quantity = int(self.twentyGP.currentText()),
                            forty_hq_quantity = int(self.fortyHQ.currentText()),
                            forty_gp_quantity = int(self.fortyGP.currentText()),
                        )
                        pay_status = apiunit.api_order_pay(self, self.auth_token, order_payload, self.paypass_edit.text())
                        if pay_status == True:
                            self.textlog(msg="下单成功，请登录网页查看")
                            self.stopBtn.click()
                            QMessageBox.information(self, '提示', '下单成功，请登录网页查看', QMessageBox.Yes)
                            self.sendMail()
                            return
                        self.booking = 0


        except BaseException as err:
            print(err)
            self.textlog(err)
            return

    def textlog(self, msg):
        print(msg)
        strftime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        self.textBrowser.append("运行信息（%s）: %s"  % (strftime, msg))

    def stopBtnClick(self):
        self.setWidgetDisabled(False)
        self.timer.stop()
        self.booking = 0

    def sendMail(self, tomail = '1929027@qq.com'):
        form_adder = 'qiangpaizhushou@163.com'  # 发送者邮箱地址
        password = 'IKEJVAYWBBGBQZLT'  # 163 授权登陆密码
        to_adder = tomail  # 接受者邮箱地址
        smtp_server = ('smtp.163.com')  # smtp 服务器
        msg = "下单参数: 20gp=%d 40gp=%d 40hq=%d 保价服务=%d" % (
        self.twentygp_num, self.fortygp_num, self.fortyhq_num, self.bl_num)
        msg = MIMEText(msg, 'plain', 'utf-8')
        msg['From'] = form_adder
        msg['To'] = to_adder
        msg['subject'] = '中远下单通知'  # 邮件标题
        try:
            server = smtplib.SMTP_SSL(smtp_server, 465)
            server.login(form_adder, password)
            server.sendmail(form_adder, [to_adder, ], msg.as_string())
            server.quit()
        except smtplib.SMTPException as e:
            print(e)
            print("Error: 无法发送邮件")
            return False
        return True


    def setTokenSlot(self, token):
        print("登录成功")
        self.auth_token = token
        self.headers['X-Auth-Token'] = token

if __name__ == '__main__':
    QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    app = QApplication(sys.argv)
    mainw = MainWindow()
    # mainw.setTokenSlot('c9e8b005-c200-4a3d-b05c-a4523ef92e05')
    # mainw.show()
    # e0f82ca3-8d99-4466-840b-5fc68cd8cd5b
    login = LoginFrom()
    login.sendToken.connect(mainw.setTokenSlot)
    login.show()
    sys.exit(app.exec_())
